/** 
 * SystemIconCache.java
 * @author Lex
 * 2007-9-5 ����12:12:28
 */
package org.lex.io.filesystem;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.filechooser.FileSystemView;

import org.lex.utils.SystemProperties;


public class FileIconCache {
	private static final String ICONS_DIRECTORY = "FileIconCache";
	// ===================================
	private Map<String, Icon> map = null;
	private FileSystemView fsv = null;
	private File cacheDir = null;

	public FileIconCache() {
		this(new File(SystemProperties.userHome()), "." + ICONS_DIRECTORY);
	}

	public FileIconCache(String iconsDirectory) {
		this(new File(SystemProperties.userHome()), iconsDirectory);
	}

	public FileIconCache(File path) {
		this(path, ICONS_DIRECTORY);
	}

	/**
	 * cached icons will be stored in "PATH/iconsDirectory"
	 * 
	 * @param path
	 * @param iconsDirectory
	 */
	public FileIconCache(File path, String iconsDirectory) {
		this.map = new ConcurrentHashMap<String, Icon>();
		fsv = FileSystemView.getFileSystemView();
		// =======================================
		cacheDir = new File(path, iconsDirectory);
		if (false == cacheDir.exists())
			cacheDir.mkdirs();
	}

	public Icon get(String extensionName) {
		Icon icon = map.get(extensionName);
		if (null == icon) {
			ln("Missed in map");
			// not found in map,we will look up icon cache directory in file
			// system
			icon = this.findInCacheDir(extensionName);
			if (null == icon) {
				// not found in file system cache dir, we have to create it;
				icon = this.createSystemIcon(extensionName);
			}
			// icon should not be null now, i guess
			map.put(extensionName, icon);
		} else {
			ln("Found in map");
		}
		return icon;
	}

	private Icon findInCacheDir(String extensionName) {
		File[] files = this.cacheDir.listFiles();
		for (File file : files) {
			String fileName = file.getName();
			String icon = "";
			int dot = fileName.lastIndexOf('.');
			if (-1 != dot)
				icon = fileName.substring(0, dot);
			if (icon.equalsIgnoreCase(extensionName)) {
				ImageIcon ii = new ImageIcon(file.getAbsolutePath());
				return ii;
			}
		}
		ln("Missed in file system cache");
		return null;
	}

	private Icon createSystemIcon(String extensionName) {
		try {
			ln("Create icon for: ." + extensionName);
			File tmp = File.createTempFile(String.valueOf(System.nanoTime()), "." + extensionName);
			Icon icon = fsv.getSystemIcon(tmp);
			tmp.delete();
			this.saveIcon(icon, extensionName);
			return icon;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	private void saveIcon(Icon icon, String name) throws IOException {
		BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
		Graphics g = img.createGraphics();
		icon.paintIcon(null, g, 0, 0);
		img.flush();
		File file = new File(cacheDir, name + ".png");
		ImageIO.write(img, "png", file);
		ln("Write to File: " + file.getAbsolutePath());
	}

	// using for debug
	private void ln(Object msg) {
	}
}
